#if 0
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
// #include "freertos/semphr.h" //二进制信号量xSemaphoreCreateBinary()
#include "freertos/message_buffer.h" //使用消息缓冲区必须要有这个头文件
#include "zhongduan.h"
#include "gatts_table_creat_demo.h" //线程缓冲区消息

#define LED GPIO_NUM_2
#define ZHONG_DUAN_1 GPIO_NUM_27

// MessageBufferHandle_t xMessageBuffer; // 此为全局变量,消息缓冲区传递消息

// 消息队列句柄
static QueueHandle_t s_queue_led = NULL;

// static QueueHandle_t gpio_sem;//二进制信号量

// 中断处理函数
static void IRAM_ATTR ledIsr(void *arg)
{
    // 向队列写true或false,虽然变量传的是地址，实际上是值传递
    if (xQueueSendFromISR(s_queue_led, (bool *)arg, NULL) != pdPASS)
        return;
    // *(bool *)arg = !*(bool *)arg; // 真假翻转
    *(bool *)arg = true;
}

// 与main并发的任务
void task_led(void *arg)
{
    // 配置GPIO2输出，此脚连接led
    gpio_set_direction(LED, GPIO_MODE_OUTPUT);
    bool led_flag = false;
    int ret = 0;
    size_t xBytesSent;
    const TickType_t x100ms = pdMS_TO_TICKS(100);
    char *pcStringToSend = "zq1";

    printf("led005\r\n");
    while (true)
    {
        // 非阻塞读，读错或队列空不影响led闪烁
        ret = xQueueReceive(s_queue_led, &led_flag, 0);
        if (led_flag)
        {
            // printf("led正在闪烁...%d\n", led_flag);
            //,将数据放入消息缓冲区,让vADifferentTask任务提取消息
            xBytesSent = xMessageBufferSend(xMessageBuffer, (void *)pcStringToSend, strlen(pcStringToSend), x100ms);
            led_flag = false;
        }
        /*
                if (led_flag)
                {
                    // printf("led正在闪烁...%d\n", led_flag);
                    gpio_set_level(LED, 1);
                    vTaskDelay(500 / portTICK_PERIOD_MS);
                    gpio_set_level(LED, 0);
                }
                else if (ret == pdPASS)
                {
                    // printf("led停止闪烁%d\n", led_flag);
                    gpio_set_level(LED, 0);
                }
        */
        vTaskDelay(200 / portTICK_PERIOD_MS);
    }
}

// 单个IO口中断初始化,参数1:IO口编号,参数2,teue为高电平上沿
bool zhong_duan_init(uint64_t ioKou)
{
#if 1 // 高电平触发
    if (gpio_install_isr_service(ESP_INTR_FLAG_LEVEL3) != ESP_OK)
    {
        printf("led中断服务错误,函数返回\r\n");
        return false;
    }
    gpio_reset_pin(ioKou);
    gpio_config_t io_t = {};
    io_t.intr_type = GPIO_INTR_POSEDGE;
    io_t.pin_bit_mask = 1ULL << ioKou;
    io_t.mode = GPIO_MODE_INPUT;
    io_t.pull_down_en = GPIO_PULLDOWN_ENABLE; // 下拉电阻,高电平触发
    gpio_config(&io_t);
    return true;
#elif 0 // 低电平触发

    if (gpio_install_isr_service(ESP_INTR_FLAG_LEVEL1) != ESP_OK)
    {
        printf("led中断服务错误,函数返回\r\n");
        return false;
    }
    gpio_reset_pin(ioKou);
    gpio_config_t io_t = {};
    io_t.intr_type = GPIO_INTR_POSEDGE;
    io_t.pin_bit_mask = 1ULL << ioKou;
    io_t.mode = GPIO_MODE_INPUT;
    io_t.pull_up_en = GPIO_PULLUP_ENABLE; // 上拉电阻,低电平后触发
    gpio_config(&io_t);
    return true;
#endif
}

void zhong_duan_H(uint64_t ioKou)
{
    gpio_reset_pin(LED); // 清除GPIO状态
    // 配置GPIO18下降沿中断并指定中断函数
    if (false == zhong_duan_init(ioKou))
    {
        printf("中断服务错误,请检查...\r\n");
        return;
    }

    printf("led001\r\n");
    // 创建消息队列
    s_queue_led = xQueueCreate(1, sizeof(bool));
    // 创建二进制信号量
    // gpio_sem = xSemaphoreCreateBinary();

    if (s_queue_led == NULL)
    {
        printf("消息队列创建失败,函数返回\r\n");
        return;
    }
    // 创建任务
    if (xTaskCreate(task_led, "led", 2048, NULL, 10, NULL) == pdFALSE)
    {
        printf("task_led创建失败,函数返回\r\n");
        return;
    }
    printf("led001-1\r\n");

    /*中断处理函数*/
    static bool s_isr_flag = true;
    gpio_isr_handler_add(ZHONG_DUAN_1, ledIsr, &s_isr_flag);
    vTaskDelay(1000 / portTICK_PERIOD_MS);
    printf("led002\r\n");
    /*
        while (true)
        {
            printf("只因你太美\n");
            vTaskDelay(4500 / portTICK_PERIOD_MS);
        }
        */
}

#elif 1

#include "c3_main.h"
#include "zhongduan.h"
#include "gatts_table_creat_demo.h" //线程缓冲区消息

#include <inttypes.h>
#include <string.h>
static const char *TAG = "zhongduan: ";
#define GPIO_INPUT_PIN 7

#define GPIO_OUTPUT_IO_0 18
#define GPIO_OUTPUT_IO_1 19
#define GPIO_OUTPUT_PIN_SEL ((1ULL << GPIO_OUTPUT_IO_0) | (1ULL << GPIO_OUTPUT_IO_1))
/*
 * Let's say, GPIO_OUTPUT_IO_0=18, GPIO_OUTPUT_IO_1=19
 * In binary representation,
 * 1ULL<<GPIO_OUTPUT_IO_0 is equal to 0000000000000000000001000000000000000000 and
 * 1ULL<<GPIO_OUTPUT_IO_1 is equal to 0000000000000000000010000000000000000000
 * GPIO_OUTPUT_PIN_SEL                0000000000000000000011000000000000000000
 * */
#define GPIO_INPUT_IO_0 4
#define GPIO_INPUT_IO_1 5
#define GPIO_INPUT_PIN_SEL ((1ULL << GPIO_INPUT_IO_0) | (1ULL << GPIO_INPUT_IO_1))
/*
 * Let's say, GPIO_INPUT_IO_0=4, GPIO_INPUT_IO_1=5
 * In binary representation,
 * 1ULL<<GPIO_INPUT_IO_0 is equal to 0000000000000000000000000000000000010000 and
 * 1ULL<<GPIO_INPUT_IO_1 is equal to 0000000000000000000000000000000000100000
 * GPIO_INPUT_PIN_SEL                0000000000000000000000000000000000110000
 * */
#define ESP_INTR_FLAG_DEFAULT 0

static QueueHandle_t gpio_evt_queue = NULL;

static void IRAM_ATTR gpio_isr_handler(void *arg)
{
    // uint32_t gpio_num = (uint32_t)arg;//传递发生中断的IO口
    bool ppdd = true;
    xQueueSendFromISR(gpio_evt_queue, &ppdd, NULL);
}
static void gpio_task_example(void *arg)
{
    size_t xBytesSent;
    char *pcStringToSend = "zq"; // unsigned char数据转换char
    const TickType_t x100ms = pdMS_TO_TICKS(100);
    bool pd = false;
    for (;;)
    {
        if (xQueueReceive(gpio_evt_queue, &pd, portMAX_DELAY))
        {
            if (pd)
            {
                xBytesSent = xMessageBufferSend(xMessageBuffer, (void *)pcStringToSend, strlen(pcStringToSend), x100ms);
                vTaskDelay(800 / portTICK_PERIOD_MS);
                pd = false;
            }

            /*
            if (io_num == GPIO_INPUT_IO_0)
            {
                // 删除 GPIO 编号的 isr 处理程序.
                gpio_isr_handler_remove(GPIO_INPUT_IO_0);
                vTaskDelay(800 / portTICK_PERIOD_MS);
                // 再次挂钩特定 GPIO 引脚的 isr 处理程序
                gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void *)GPIO_INPUT_IO_0);
            }
            else if (io_num == GPIO_INPUT_IO_1)
            {
                gpio_isr_handler_remove(GPIO_INPUT_IO_1);
                vTaskDelay(800 / portTICK_PERIOD_MS);
                // 再次挂钩特定 GPIO 引脚的 isr 处理程序
                gpio_isr_handler_add(GPIO_INPUT_IO_1, gpio_isr_handler, (void *)GPIO_INPUT_IO_1);
            }*/
            // printf("GPIO[%"PRIu32"] intr, val: %d\n", io_num, gpio_get_level(io_num));
        }
    }
}

// 中断初始化,参数1:IO口编号
void zhong_duan_init()
{
#if 1 // 高电平触发
    // 对配置结构进行零初始化.
    gpio_config_t io_conf = {};
#if 0
    // 禁用中断
    io_conf.intr_type = GPIO_INTR_DISABLE;
    // 设置为输出模式
    io_conf.mode = GPIO_MODE_OUTPUT;
    // 您要设置的引脚的位掩码，例如GPIO18/19
    io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL;
    // 禁用下拉模式
    io_conf.pull_down_en = 0;
    // 禁用上拉模式
    io_conf.pull_up_en = 0;
    // 使用给定设置配置 GPIO
    gpio_config(&io_conf);
#endif
    // 上升沿中断
    io_conf.intr_type = GPIO_INTR_ANYEDGE;
    // 引脚的位掩码，此处使用 GPIO4/5
    io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;
    // 设置为输入模式
    io_conf.mode = GPIO_MODE_INPUT;
    // 使能上拉模式
    // io_conf.pull_up_en = 1;
    io_conf.pull_down_en = GPIO_PULLDOWN_ENABLE;
    gpio_config(&io_conf);

    // 更改一个引脚的 GPIO 中断类型
    // gpio_set_intr_type(GPIO_INPUT_IO_0, GPIO_INTR_ANYEDGE);

    // 创建一个队列来处理来自 isr 的 gpio 事件
    gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
    // 启动GPIO任务
    xTaskCreate(gpio_task_example, "gpio_task_example", 2048, NULL, 10, NULL);

    // 安装gpio isr服务
    gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
    // 针对特定 GPIO 引脚的钩子 isr 处理程序
    gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void *)GPIO_INPUT_IO_0);
    // 针对特定 GPIO 引脚的钩子 isr 处理程序
    gpio_isr_handler_add(GPIO_INPUT_IO_1, gpio_isr_handler, (void *)GPIO_INPUT_IO_1);

    // 删除 GPIO 编号的 isr 处理程序.
    // gpio_isr_handler_remove(GPIO_INPUT_IO_0);
    // 再次挂钩特定 GPIO 引脚的 isr 处理程序
    // gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void *)GPIO_INPUT_IO_0);

    // printf("Minimum free heap size: %" PRIu32 " bytes\n", esp_get_minimum_free_heap_size());
/*
    int cnt = 0;
    while (1)
    {
        printf("ppppppcntssssss : %d\n", cnt++);
        vTaskDelay(6000 / portTICK_PERIOD_MS);
        gpio_set_level(GPIO_OUTPUT_IO_0, cnt % 2);
        gpio_set_level(GPIO_OUTPUT_IO_1, cnt % 2);
    }
    */
#elif 0 // 低电平触发

    if (gpio_install_isr_service(ESP_INTR_FLAG_LEVEL1) != ESP_OK)
    {
        printf("led中断服务错误,函数返回\r\n");
        return false;
    }
    gpio_reset_pin(ioKou);
    gpio_config_t io_t = {};
    io_t.intr_type = GPIO_INTR_POSEDGE;
    io_t.pin_bit_mask = 1ULL << ioKou; // 1ULL << ioKou是重点,不是直接传IO口
    io_t.mode = GPIO_MODE_INPUT;
    io_t.pull_up_en = GPIO_PULLUP_ENABLE; // 上拉电阻,低电平后触发
    gpio_config(&io_t);
#endif
}

#endif